var tests = {
    name: "Uncategorized"
};
tests.prv = {};
tests.scenarios = {};

tests.prv.PASS = "pass";
tests.prv.FAIL = "fail";
tests.prv.WARN = "warn";
tests.prv.ERROR = "error";

function TestResult(resultParam, resultTextParam, resultInfo) {
    this.result = resultParam;
    this.resultText = resultTextParam;
    this.resultInfo = resultInfo;
}

tests.prv.createMock = function(proto) {
    var mockCreator = function() {
    };
    mockCreator.prototype = proto;
    return new mockCreator();
}

tests.prv.evaluateTest = function(testCase) {
    var result = null;

    if (typeof(testCase) === 'function') {
        try {
            var testResult = testCase();
        } catch (e) {
            result = new TestResult(tests.prv.ERROR, tests.prv
                .getObjectString(e));
        }
        if (result === null) {
            if (!testResult) {
                result = new TestResult(tests.prv.ERROR, "Result is null");
            } else if (testResult === true) {
                result = new TestResult(tests.prv.PASS, "Pass");
            } else if (testResult === false) {
                result = new TestResult(tests.prv.FAIL, "Fail");
            } else if (testResult.result !== undefined) {
                var message = testResult.resultMessage || "N/A";
                result = new TestResult(testResult.result === true
                    ? tests.prv.PASS
                    : tests.prv.FAIL, testResult.result === true
                    ? "Pass"
                    : "Fail",
                    (testResult.step)?
                    "[" + testResult.step + "] " + message :
                    message);
            } else {
                result = new TestResult(tests.prv.WARN, tests.prv
                    .getObjectString(testResult));
            }
        }
    } else {
        result = new TestResult(tests.prv.WARN, "Not a function: "
            + tests.prv.getObjectString(testCase));
    }
    return result;
}

tests.prv.ResultObject = function() {
    this.step = "";
    this.result = true;
    this.resultMessage = "";
    this.createAssert = function() {
        var that = this;
        var assert = function (val) {
            that.step += (val)?".":"x";
            that.result = that.result && (val === true);
        };
            
        return assert;
    }
    this.setResultMessage = function(param) {
        this.resultMessage = tests.prv.getObjectString(param);
    }
}

tests.prv.getObjectString = function(obj) {
    var returnText = "";
    var objType = typeof(obj);
    if (obj === null || obj === undefined) {
        returnText = "empty";
    } else if (objType === 'string') {
        returnText = obj.replace(/"/g, "&quot;");
    } else {
        returnText = "[";
        for (var key in obj) {
            var value = obj[key];
            if(typeof value === "string") {
                value = value.replace(/"/g, "&quot;");
            }
            returnText += "'" + ((typeof key === "string")?key.replace(/"/g, "&quot;"):key) + "' : '" + value + "', ";
        }
        returnText += "]";
    }
    return returnText;
}

tests.prv.getStringElement = function(msg, title) {
    if (msg && msg.length > 50) {
        return "<spam title=\"" + (title) ? (title + " - " + msg) : msg + "\">"
        + msg.substring(0, 47) + "..." + "</spam>";
    } else if (msg) {
        if (title) {
            return "<spam title=\"" + title + "\">" + msg + "</spam>";
        }
        return msg;
    } else
        return "empty";
}

tests.prv.getTableRow = function(count, testName, testResult) {
    var tableRow = "<tr><td class=\"count\">";
    tableRow += count + ".";
    tableRow += "</td><td class=\"testname\">";
    tableRow += testName;
    tableRow += "</td><td class=\"" + testResult.result + "\">";
    tableRow += tests.prv.getStringElement(testResult.resultText,
        testResult.resultInfo);
    tableRow += "</td></tr>";

    return tableRow;
}

tests.prv.getSummaryString = function(summary) {
    var summaryString = "<span style=\"font-weight: bold;\">Summary:</span> ";
    for (var key in summary) {
        summaryString += "<span class=\"" + key + "\">"
        summaryString += key;
        summaryString += ": ";
        summaryString += summary[key];
        summaryString += "</span> ";
    }
    return summaryString;
}

tests.prv.executeTests = function(baseObj, summary) {
    if(baseObj) {
        var result = "<br />\n";
        result += "<table>\n";
        if(baseObj.name) {
            result += "<caption style=\"text-align: left; font-weight: bold;\">"+baseObj.name+"</caption>\n";
        }
        var count = 0;
        for (testName in baseObj) {
            if (baseObj.hasOwnProperty(testName)) {
                var testObj = baseObj[testName];
                if (typeof(testObj) === 'function') {
                    count++;
                    var testResult = tests.prv.evaluateTest(testObj);
                    summary[testResult.result] = summary[testResult.result] + 1;
                    result += tests.prv.getTableRow(count, testName,
                        testResult);
                    result += "\n";
                }
            }
        }
        result += "</table>\n";
        if(count > 0) {
            return result;
        }
        return;
    } else {
        return;
    }
}

function test() {
    var testResult;
    var summary = {};
    summary[tests.prv.PASS] = 0;
    summary[tests.prv.FAIL] = 0;
    summary[tests.prv.WARN] = 0;
    summary[tests.prv.ERROR] = 0;
    document.writeln("<div id=\"summary\">Tests are running...</div>");
    if(tests) {
        var count = 0;
        var result = "";
        if(tests.scenarios) {
            for(var scenario in tests.scenarios) {
                testResult = tests.prv.executeTests(tests.scenarios[scenario], summary);
                if(testResult) {
                    result += testResult;
                    result += "\n";
                    count++;
                }
            }
        }
        testResult = tests.prv.executeTests(tests, summary);
        if(testResult) {
            result += testResult;
            result += "\n";
            count++;
        }
    }
    if(count > 0) {
        document.writeln(result);
    }
	
    document.getElementById('summary').innerHTML = tests.prv
    .getSummaryString(summary);
}
